Skip to content

Fix BidirectionalRelay half-close handling - #41328

Closed
Eamon (Eamon2009) wants to merge 3 commits into
microsoft:masterfrom
Eamon2009:patch-3
Closed

Fix BidirectionalRelay half-close handling#41328
Eamon (Eamon2009) wants to merge 3 commits into
microsoft:masterfrom
Eamon2009:patch-3

Conversation

@Eamon2009

@Eamon2009 Eamon (Eamon2009) commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

BidirectionalRelay exited as soon as one side closed (||), dropping any buffered data the other side still had to send. Changed to && so both directions drain before exit, matching the guest-side fix in localhost_relay.cpp.

This completes end-to-end half-close handling: a Windows client that calls shutdown(SD_SEND) can now reliably receive the Linux server's response.
#41326

Fix logical condition and handle EOF in relay.cpp
Copilot AI lite review requested due to automatic review settings August 12, 2026 18:02
@Eamon2009
Eamon (Eamon2009) requested a review from a team as a code owner August 12, 2026 18:02
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts the Windows-side relay implementation (src/windows/common/relay.cpp) to better handle half-close semantics and prevent a CPU spin when ReadFile reports an EOF via BytesRead == 0.

Changes:

  • Updated BidirectionalRelay loop termination to wait for both directions to complete (changed || to &&).
  • Updated ScopedMultiRelay::Run to treat synchronous ReadFile(...)=TRUE with BytesRead == 0 as EOF and transition to Eof.
Suppressed comments (1)

src/windows/common/relay.cpp:323

  • With the loop now exiting only when both handles are null, hitting EOF on one side (where the code sets LeftHandle = nullptr / RightHandle = nullptr) causes the relay to keep reading from the other side but skip the corresponding write (else if (RightHandle != nullptr) / else if (LeftHandle != nullptr)), effectively dropping data rather than draining it. To support TCP half-close correctly, consider tracking read-EOF state separately (e.g., leftReadClosed/rightReadClosed) while keeping the HANDLE for writes, and only stopping writes on actual write failure.
        if ((LeftHandle == nullptr) && (RightHandle == nullptr))
        {
            break;
        }


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Eamon2009
Eamon (Eamon2009) marked this pull request as draft August 12, 2026 18:10
Copilot AI review requested due to automatic review settings August 12, 2026 18:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment on lines +321 to 324
if (leftReadClosed && rightReadClosed)
{
break;
}
Comment thread src/windows/common/relay.cpp Outdated
Comment on lines +298 to +301
bool leftReadPending = false;
bool rightReadPending = false;
bool leftReadClosed = false;
bool rightReadClosed = false;
Change || to && so both directions drain before the relay exits.
Copilot AI review requested due to automatic review settings August 12, 2026 18:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/windows/common/relay.cpp:301

  • BidirectionalRelay is declared with _In_ HANDLE LeftHandle/RightHandle (non-null), and current call sites pass non-null handles. Initializing leftReadClosed/rightReadClosed from == nullptr is therefore redundant/misleading; either assert the non-null contract here or (if nullptr is valid) the API should be _In_opt_ and documented accordingly.
    bool leftReadClosed = (LeftHandle == nullptr);
    bool rightReadClosed = (RightHandle == nullptr);

@Eamon2009 Eamon (Eamon2009) changed the title Fix Windows relay half-close and sync-success EOF spin Fix BidirectionalRelay half-close handling Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants